#! /usr/bin/env node

/*************************************************************************
 *
 *  direct/tex2svg
 *
 *  Uses MathJax v3 to convert a TeX string to an SVG string.
 *
 * ----------------------------------------------------------------------
 *
 *  Copyright (c) 2018 The MathJax Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

//
//  Load the packages needed for MathJax
//
const {mathjax} = require('mathjax-full/js/mathjax.js');
const {TeX} = require('mathjax-full/js/input/tex.js');
const {SVG} = require('mathjax-full/js/output/svg.js');
const {liteAdaptor} = require('mathjax-full/js/adaptors/liteAdaptor.js');
const {RegisterHTMLHandler} = require('mathjax-full/js/handlers/html.js');
const {AssistiveMmlHandler} = require('mathjax-full/js/a11y/assistive-mml.js');

const {AllPackages} = require('mathjax-full/js/input/tex/AllPackages.js');

//
//  Minimal CSS needed for stand-alone image
//
const CSS = [
  'svg a{fill:blue;stroke:blue}',
  '[data-mml-node="merror"]>g{fill:red;stroke:red}',
  '[data-mml-node="merror"]>rect[data-background]{fill:yellow;stroke:none}',
  '[data-frame],[data-line]{stroke-width:70px;fill:none}',
  '.mjx-dashed{stroke-dasharray:140}',
  '.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}',
  'use[data-c]{stroke-width:3px}'
].join('');

//
//  Get the command-line arguments
//
var argv = require('yargs')
    .demand(0).strict()
    .usage('$0 [options] "math" > file.svg')
    .options({
      inline: {
        boolean: true,
        describe: "process as inline math"
      },
      em: {
        default: 16,
        describe: 'em-size in pixels'
      },
      ex: {
        default: 8,
        describe: 'ex-size in pixels'
      },
      width: {
        default: 80 * 16,
        describe: 'width of container in pixels'
      },
      packages: {
        default: AllPackages.sort().join(', '),
        describe: 'the packages to use, e.g. "base, ams"'
      },
      styles: {
        boolean: true,
        default: true,
        describe: 'include css styles for stand-alone image'
      },
      container: {
        boolean: true,
        describe: 'include <mjx-container> element'
      },
      css: {
        boolean: true,
        describe: 'output the required CSS rather than the SVG itself'
      },
      fontCache: {
        boolean: true,
        default: true,
        describe: 'whether to use a local font cache or not'
      },
      assistiveMml: {
        boolean: true,
        default: false,
        describe: 'whether to include assistive MathML output'
      }
    })
    .argv;

//
//  Create DOM adaptor and register it for HTML documents
//
const adaptor = liteAdaptor();
const handler = RegisterHTMLHandler(adaptor);
if (argv.assistiveMml) AssistiveMmlHandler(handler);

//
//  Create input and output jax and a document using them on the content from the HTML file
//
const tex = new TeX({packages: argv.packages.split(/\s*,\s*/)});
const svg = new SVG({fontCache: (argv.fontCache ? 'local' : 'none')});
const html = mathjax.document('', {InputJax: tex, OutputJax: svg});

//
//  Typeset the math from the command line
//
const node = html.convert(argv._[0] || '', {
  display: !argv.inline,
  em: argv.em,
  ex: argv.ex,
  containerWidth: argv.width
});

//
//  If the --css option was specified, output the CSS,
//  Otherwise, typeset the math and output the HTML
//
if (argv.css) {
  console.log(adaptor.textContent(svg.styleSheet(html)));
} else {
  let html = (argv.container ? adaptor.outerHTML(node) : adaptor.innerHTML(node));
  console.log(argv.styles ? html.replace(/<defs>/, `<defs><style>${CSS}</style>`) : html);
}
